package model;
import controller.IllegalPositionException;
import model.GameColor;

/* Positions on Board  [z,y,x]
 * 000--------------001--------------002
 * |				 |			   	  |
 * |	100---------101---------102   |
 * |     |           |           |    |
 * |	 |	 200----201----202   |    |
 * |     |    |              |   |    |
 * 010--110--210			212--112--012
 * |     |    |              |   |    |
 * |	 |	 220----221-----222  |    |
 * |     |           |           |    |
 * |	120---------121---------122	  |
 * |                 |                |
 * 020--------------021--------------022
 * 
 * z identify the quad
 * y identify the row in a quad
 * x identify the column in a quad
 * 
 * Allowed Mills are represented by lines.
 * 
 */ 




public class Board {
	
	private GameColor[][][] board; 
	
	public Board() {
		board = new GameColor[3][3][3];
		this.reset();
	}
	public Board(GameColor[][][] board){
		this.board = board;
		this.reset();
	}
	
	public void reset() {
		for(int z = 0; z < 3; z++){
			for(int y = 0; y < 3; y++){
				for(int x = 0; x < 3; x++){
					if(!isValid(z, y, x)){
							if(y == 1 && x == 1){
								board[z][y][x] = GameColor.Invalid;
							}else{
								board[z][y][x] = GameColor.Empty;
							}
					}
				}
			}
		}
	}
	
	public String toString(){//Was eine Sch...
		return getColor(0, 0, 0).getColor()+"------------"+getColor(0, 0, 1).getColor()+"------------"+getColor(0, 0, 2).getColor()+"\n"+
		"|            |            |\n"+
		"|   "+getColor(1, 0, 0).getColor()+"--------"+getColor(1, 0, 1).getColor()+"--------"+getColor(1, 0, 2).getColor()+"   |\n"+
		"|   |        |        |   |\n"+
		"|   |	"+getColor(2, 0, 0).getColor()+"----"+getColor(2, 0, 1).getColor()+"----"+getColor(2, 0, 2).getColor()+"   |   |\n"+
		"|   |   |         |   |   |\n"+
		getColor(0, 1, 0).getColor()+"---"+getColor(1, 1, 0).getColor()+"---"+getColor(2, 1, 0).getColor()+"         "+getColor(2, 1, 2).getColor()+"---"+getColor(1, 1, 2).getColor()+"---"+getColor(0, 1, 2).getColor()+"\n"+
		"|   |   |         |   |   |\n"+
		"|   |   "+getColor(2, 2, 0).getColor()+"----"+getColor(2, 2, 1).getColor()+"----"+getColor(2, 2, 2).getColor()+"   |   |\n"+
		"|   |        |        |   |\n"+
		"|   "+getColor(1, 2, 0).getColor()+"--------"+getColor(1, 2, 1).getColor()+"--------"+getColor(1, 2, 2).getColor()+"	  |\n"+
		"|            |            |\n"+
		getColor(0, 2, 0).getColor()+"------------"+getColor(0, 2, 1).getColor()+"------------"+getColor(0, 2, 2).getColor()+"\n";
	}

	public boolean isStoneInMill(int z, int y, int x) {
		GameColor color = this.getColor(z, y, x);
		
		if(checkQuadMill(z, y, x, color)){
			return true;
		}
		
		if(checkOverQuadMill(z, y, x, color)){
			return true;
		}
			
		return false;
	}
	
	public boolean isStoneInMill(int z, int y, int x, GameColor color) {		
		if(checkQuadMill(z, y, x, color)){
			return true;
		}
		
		if(checkOverQuadMill(z, y, x, color)){
			return true;
		}
			
		return false;
	}
	
	private boolean checkQuadMill(int z, int y, int x, GameColor c){		
			//check Rows
			if(x == 0){
				if(this.getColor(z, y, 1) == c && this.getColor(z, y, 2) == c){
					return true;
				}
			}
			if(x == 1){
				if(this.getColor(z, y, 0) == c && this.getColor(z, y, 2) == c){
					return true;
				}
			}

			if(x == 2){
				if(this.getColor(z, y, 0) == c && this.getColor(z, y, 1) == c){
					return true;
				}
			}
			
			//check Column
			if(y == 0){
				if(this.getColor(z, 1, x) == c && this.getColor(z, 2, x) == c){
					return true;
				}
			}
			if(y == 1){
				if(this.getColor(z, 0, x) == c && this.getColor(z, 2, x) == c){
					return true;
				}
			}

			if(y == 2){
				if(this.getColor(z, 0, x) == c && this.getColor(z, 1, x) == c){
					return true;
				}
			}
		return false;
	}
	
	private boolean checkOverQuadMill(int z, int y, int x, GameColor c){
		if(z == 0){
			if(this.getColor(1, y, x) == c && this.getColor(2, y, x) == c){
				return true;
			}
		}	
		if(z == 1){
			if(this.getColor(0, y, x) == c && this.getColor(2, y, x) == c){
				return true;
			}
		}
		if(z == 2){
			if(this.getColor(0, y, x) == c && this.getColor(1, y, x) == c){
				return true;
			}
		}
		return false;
	}
	
	public GameColor getPosition(int z, int y, int x){		
		return board[z][y][x];
	}
	
	public void setStone(int z, int y, int x, GameColor current_aktive_Color) throws IllegalPositionException{		
		if(checkPosition(z, y, x)){
			board[z][y][x] = current_aktive_Color;
		}		
	}
	
	public void removeStone(int z, int y, int x, GameColor current_aktive_Color) throws IllegalPositionException{
		boolean isInMill = false;
		if(current_aktive_Color == GameColor.Black){
			isInMill = isStoneInMill(z, y, x, GameColor.White);
		}else{
			isInMill = isStoneInMill(z, y, x, GameColor.Black);
		}
		if(checkPosition(z, y, x) && !isInMill){
			board[z][y][x] = GameColor.Empty;
		}else{
			throw new IllegalPositionException(); //TODO
		}
	}
	
	/* Method from Position */
	public boolean compareTo(int z, int y, int x, GameColor gameColor) {
		// TODO Auto-generated method stub
		return false;
	}

	public boolean checkPosition(int z, int y, int x) throws IllegalPositionException {
		if(!isEmpty(z, y, x) || isValid(z, y, x)){
			throw new IllegalPositionException();
		}
		return true;
	}
	
	public GameColor getColor(int z, int y, int x) {
		return board[z][y][x];
	}

	private boolean isValid(int z, int y, int x) {
		if (board[z][y][x] == GameColor.Invalid){
			return true;
		}
		return false;
	}
	
	private boolean isEmpty(int z, int y, int x) {
		if (board[z][y][x] == GameColor.Empty){
			return true;
		}
		return false;
	}
	public boolean playerHasMoveLeft(Player player) {
		if(player.getFreeStones() > 0 || player.getStonesOnBoard() <= 3){
			return true;
		}
		//Check if at least one possible move is left
		for(int z = 0; z <=3 ; z++){
			for(int y = 0; y <= 3; y++){
				for(int x = 0; x <= 3; x++){
					if(getColor(z, y, x) == player.getColor()){
						if(checkQuadMoves(z, y, x) || checkOverQuadMove(z, y, x)){
							return true;
						}
					}
				}
			}
		}
		return false;
	}
	
	private boolean checkQuadMoves(int z, int y, int x){		
		//check Rows
		if(x == 0){
			if(this.getColor(z, y, 1) == GameColor.Empty || this.getColor(z, y, 2) == GameColor.Empty){
				return true;
			}
		}
		if(x == 1){
			if(this.getColor(z, y, 0) == GameColor.Empty || this.getColor(z, y, 2) == GameColor.Empty){
				return true;
			}
		}

		if(x == 2){
			if(this.getColor(z, y, 0) == GameColor.Empty || this.getColor(z, y, 1) == GameColor.Empty){
				return true;
			}
		}
		
		//check Column
		if(y == 0){
			if(this.getColor(z, 1, x) == GameColor.Empty || this.getColor(z, 2, x) == GameColor.Empty){
				return true;
			}
		}
		if(y == 1){
			if(this.getColor(z, 0, x) == GameColor.Empty || this.getColor(z, 2, x) == GameColor.Empty){
				return true;
			}
		}

		if(y == 2){
			if(this.getColor(z, 0, x) == GameColor.Empty || this.getColor(z, 1, x) == GameColor.Empty){
				return true;
			}
		}
	return false;
}

private boolean checkOverQuadMove(int z, int y, int x){
	if(z == 0){
		if(this.getColor(1, y, x) == GameColor.Empty || this.getColor(2, y, x) == GameColor.Empty){
			return true;
		}
	}	
	if(z == 1){
		if(this.getColor(0, y, x) == GameColor.Empty || this.getColor(2, y, x) == GameColor.Empty){
			return true;
		}
	}
	if(z == 2){
		if(this.getColor(0, y, x) == GameColor.Empty || this.getColor(1, y, x) == GameColor.Empty){
			return true;
		}
	}
	return false;
}

}
